﻿using System.Collections.Generic;
using System.ComponentModel;
using Model;
using Communicator;
using System;
using System.Threading;

namespace SoundConstructor
{
	class Imitator
	{
		static Imitator theInstance = new Imitator();

		Communicator.Communicator communicator;
		AudioPlayer audioPlayer;
		private List<OnetimeSound> onetimeSounds;
		private List<RepeatedSound> repeatedSounds;

		internal static Imitator Instance
		{
			get { return theInstance; }
		}

		public Communicator.Communicator Communicator
		{
			set { communicator = value; }
		}

		public AudioPlayer AudioPlayer
		{
			set { audioPlayer = value; }
		}

		public List<OnetimeSound> OnetimeSounds
		{
			set { onetimeSounds = value; }
		}

		public List<RepeatedSound> RepeatedSounds
		{
			set { repeatedSounds = value; }
		}

		private Imitator()
		{
			
		}

		internal void StartImitation()
		{
			BindCommunicatorEventsWithHandlers();
			RegisterAllXmlParametersOfAllSounds();
			StartListeningToNetwork();
		}

		private void BindCommunicatorEventsWithHandlers()
		{
			communicator.DataExchange += new EventHandler<EventArgs>(Communicator_DataExchange);
			communicator.DataReceived += new EventHandler<EventArgs>(Communicator_DataReceived);
			communicator.DataSent += new EventHandler<global::Communicator.Communicator.ParameterInfoEventArgs>(Communicator_DataSent);		
		}

		private void Communicator_DataExchange(object sender, EventArgs e)
		{
			UpdateAllXmlParametersValuesOfAllSounds();
			PlayAllSounds();
		}

		private void Communicator_DataSent(object sender, Communicator.Communicator.ParameterInfoEventArgs e)
		{
			UpdateAllXmlParametersValuesOfAllSounds();
			PlayAllSounds();
		}

		private void Communicator_DataReceived(object sender, EventArgs e)
		{
			UpdateAllXmlParametersValuesOfAllSounds();
			PlayAllSounds();
		}

		private void RegisterAllXmlParametersOfAllSounds()
		{
			RegisterAllXmlParametersOfAllOnetimeSounds();
			RegisterAllXmlParametersOfAllRepeatedSounds();
		}

		private void RegisterAllXmlParametersOfAllOnetimeSounds()
		{
			foreach (OnetimeSound sound in onetimeSounds)
			{
				communicator.AddParameter(sound.XmlParameterName, ParameterDirection.input);
			}
		}

		private void RegisterAllXmlParametersOfAllRepeatedSounds()
		{
			foreach (RepeatedSound sound in repeatedSounds)
			{
				communicator.AddParameter(sound.NameOfXmlParameterForVolume, ParameterDirection.input);
				communicator.AddParameter(sound.NameOfXmlParameterForFrequency, ParameterDirection.input);
				//communicator.AddParameter(sound.NameOfXmlParameterForEcho, ParameterDirection.input);
			}
		}

		private void StartListeningToNetwork()
		{
			communicator.Start();
		}
		
		private void UpdateAllXmlParametersValuesOfAllSounds()
		{
			UpdateAllXmlParametersValuesOfAllOnetimeSounds();
			UpdateAllXmlParametersValuesOfAllRepeatedSounds();
		}

		private void UpdateAllXmlParametersValuesOfAllOnetimeSounds()
		{
			foreach (OnetimeSound sound in onetimeSounds)
			{
				sound.XmlParameterValue = 
					Convert.ToDouble(communicator.GetParameterValueByName(sound.XmlParameterName));
			}			
		}

		private void UpdateAllXmlParametersValuesOfAllRepeatedSounds()
		{
			foreach (RepeatedSound sound in repeatedSounds)
			{
				sound.ValueOfXmlParameterForVolume = 
					Convert.ToDouble(communicator.GetParameterValueByName(sound.NameOfXmlParameterForVolume));
				sound.ValueOfXmlParameterForFrequency =
					Convert.ToDouble(communicator.GetParameterValueByName(sound.NameOfXmlParameterForFrequency));
				//sound.ValueOfXmlParameterForEcho =
				//	Convert.ToDouble(communicator.GetParameterValueByName(sound.NameOfXmlParameterForEcho));
			}	
		}

		private void PlayAllSounds()
		{
			PlayAllOnetimeSounds();
			PlayAllRepeatedSounds();
		}

		private void PlayAllOnetimeSounds()
		{
			foreach (OnetimeSound sound in onetimeSounds)
			{
				audioPlayer.Play(sound.Name, sound.MaxDuration, sound.BlockRepeat,
					sound.Volume, sound.Frequency, sound.SoundFileLocation);
			}
		}

		private void PlayAllRepeatedSounds()
		{
			foreach (RepeatedSound sound in repeatedSounds)
			{
				    audioPlayer.Play(sound.Name, sound.Volume, sound.Frequency, 
					sound.Echo, sound.SoundFileLocation);
			}
		}

		internal void StopImitation()
		{
			StopListeningToNetwork();
			StopPlayingSounds();
		}

		private void StopPlayingSounds()
		{
			StopPlayingOnetimeSounds();
			StopPlayingRepeatedSounds();
		}

		private void StopPlayingOnetimeSounds()
		{
			foreach (OnetimeSound sound in onetimeSounds)
			{
				audioPlayer.Stop(sound.Name);
			}
		}

		private void StopPlayingRepeatedSounds()
		{
			foreach (RepeatedSound sound in repeatedSounds)
			{
				audioPlayer.Stop(sound.Name);
			}
		}

		private void StopListeningToNetwork()
		{
			communicator.Stop();
		}
	}
}
